Skip to content

hardening: migrate flowview process/version lookups to prepared - #248

Merged
TheWitness merged 11 commits into
Cacti:developfrom
somethingwithproof:fix/prepared-lookups-247
Sep 15, 2026
Merged

TheWitness merged 11 commits into
Cacti:developfrom
somethingwithproof:fix/prepared-lookups-247

Conversation

@somethingwithproof

@somethingwithproof somethingwithproof commented Mar 15, 2026

Copy link
Copy Markdown
Member

Summary

Implements issue #247 by migrating selected raw process/version lookups to prepared database helpers, and fixes #239 by replacing a non-portable bitwise CIDR match in get_ip_filter() with a range comparison.

Changes

  • flowview_devices.php
    • converted process PID lookup in save_device() to db_fetch_cell_prepared()
    • converted process PID lookup in restart_services() to db_fetch_cell_prepared()
  • setup.php
    • converted plugin version lookup in plugin_flowview_check_config() to db_fetch_cell_prepared()
    • converted process PID lookup in flowview_global_settings_update() to db_fetch_cell_prepared()
  • functions.php
    • get_ip_filter() matched CIDR ranges with a bitwise AND against a VARBINARY column, which MySQL 8.0 evaluates correctly but MariaDB casts to BIGINT and always matches, so every row passed the filter. Replaced with a LENGTH()-guarded BETWEEN range comparison, portable across both servers, per @somethingwithproof's diagnosis and suggested fix in Flowview not taking account of the filter src/dst IP #239.
  • added regression test: tests/test_prepared_statements.php
  • test suite: tests/Unit/QueryBuilderTest.php updated for the new CIDR range predicate/params

Validation

  • php -l flowview_devices.php
  • php -l setup.php
  • php -l tests/test_prepared_statements.php
  • php tests/test_prepared_statements.php

Issue

Closes #247
Closes #239

Copilot AI review requested due to automatic review settings March 15, 2026 23:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates FlowView plugin code to replace raw SQL string queries with prepared statements, and adds a lightweight regression test to detect reintroduction of those raw lookups.

Changes:

  • Converted plugin version lookup in setup.php to db_fetch_cell_prepared() with a bound placeholder.
  • Converted FlowView master process PID lookups in setup.php and flowview_devices.php to db_fetch_cell_prepared() with bound placeholders.
  • Added a PHP test script that scans source files to assert prepared-statement usage and absence of specific raw lookups.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
tests/test_prepared_statements.php Adds string-based regression checks to enforce prepared-statement usage for specific queries.
setup.php Replaces raw db_fetch_cell() lookups with db_fetch_cell_prepared() for plugin version and PID retrieval.
flowview_devices.php Replaces raw PID lookups with prepared statements for save/restart service paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread tests/test_prepared_statements.php Outdated
Comment thread tests/test_prepared_statements.php Outdated
@somethingwithproof somethingwithproof changed the title security: migrate flowview process/version lookups to prepared hardening: migrate flowview process/version lookups to prepared Mar 15, 2026
@somethingwithproof

somethingwithproof commented Mar 16, 2026

Copy link
Copy Markdown
Member Author

Incorporated follow-up review feedback in da408cb. Added follow-up checks to verify process lookups bind flowview/master via placeholders in both setup and device paths.

@somethingwithproof
somethingwithproof marked this pull request as draft March 20, 2026 10:00
@TheWitness

Copy link
Copy Markdown
Member

Looks like after the last merge, you should update your branch @somethingwithproof

Add targeted tests for prepared statement migration, output escaping,
auth guard presence, CSRF token validation, redirect safety, and
PHP 7.4 compatibility. Tests use source-scan patterns that verify
security invariants without requiring the Cacti database.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
@somethingwithproof
somethingwithproof force-pushed the fix/prepared-lookups-247 branch from 2ffba84 to acea08d Compare July 29, 2026 05:35
@somethingwithproof
somethingwithproof marked this pull request as ready for review August 29, 2026 05:54
@somethingwithproof somethingwithproof self-assigned this Sep 6, 2026

@TheWitness TheWitness left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No composer.json in plugins.

xmacan
xmacan previously approved these changes Sep 15, 2026
# Conflicts:
#	tests/Pest.php
#	tests/Security/Php74CompatibilityTest.php
#	tests/Security/SetupStructureTest.php


- drop composer.json and tests/bootstrap.php; Pest and the Cacti API
  stubs now come from tests/bootstrap-unit.php via phpunit.xml, same as
  every other suite in this repo
- move the E2E and Integration regression tests into tests/Security,
  since they are static source-scan checks like the rest of that suite
  and phpunit.xml only scans tests/Security and tests/Unit
…acti#239)

get_ip_filter() masked VARBINARY addresses with a bitwise AND, which MySQL 8.0 evaluates correctly but MariaDB casts both sides to BIGINT and always matches, silently returning every row. Replace it with a LENGTH()-guarded BETWEEN range, which is portable across both servers and keeps a 4-byte IPv4 range from reaching 16-byte IPv6 rows.

Reported and diagnosed by @somethingwithproof in Cacti#239, whose suggested fix this applies verbatim.

Closes Cacti#239
…harness

Verified with a sandbox Cacti checkout (Pest 3 + phpunit.xml from Cacti#260):

- AuthGuardTest/OutputEscapingTest/RedirectSafetyTest/PreparedStatementConsistencyTest
  scanned tests/test_prepared_statements.php itself as if it were a UI entry
  point, which isn't meaningful for a test script; drop it from those scan
  lists.
- PreparedStatementConsistencyTest flagged setup.php's two db_execute() calls
  that create the core Cacti reports_log/reports_queued tables. Those are
  static CREATE TABLE DDL with no bound values, so there is nothing to
  parameterize; exclude DDL lines from the raw-call check.

All 61 tests in tests/Security and tests/Unit now pass.

@bmfmancini bmfmancini left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving — the prepared-statement migration for the process/version lookups, the port normalization before shell_exec, and the MariaDB-portable LENGTH()/BETWEEN CIDR range predicate in get_ip_filter() all look correct. Regression tests cover the changes well.

@TheWitness
TheWitness merged commit 035d1ed into Cacti:develop Sep 15, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hardening: migrate remaining process/version lookups to prepared helpers Flowview not taking account of the filter src/dst IP

5 participants